package com.zhz.mall.common.util.transaction;

import cn.hutool.core.lang.Assert;
import com.zhz.mall.common.api.CommonResult;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.function.Supplier;

/**
 * TransactionHandler
 * <p>
 * 编程式事务（注意和 TransactionTemplate 的不同）
 *
 * @see TransactionUtils
 */
@Component
public class TransactionHandler {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private TransactionHandler transactionHandler;

    @Transactional(rollbackFor = Throwable.class)
    public <T> T execute(Supplier<T> task) {
        return task.get();
    }

    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW)
    public <T> T executeWithNewTransaction(Supplier<T> task) {
        return task.get();
    }


    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW)
    public <T> CommonResult<T> autoExecuteWithNewTransaction(Supplier<CommonResult<T>> task) {
        return TransactionUtils.setRollbackOnly(task.get());
    }


    /**
     * 处理失败, 自动回滚事务
     */
    @Transactional(rollbackFor = Throwable.class)
    public <T> CommonResult<T> autoExecute(Supplier<CommonResult<T>> task) {
        return TransactionUtils.setRollbackOnly(task.get());
    }


//    @DistributedLock
    public <T> T executeWithLock(String value, Supplier<T> task) {
        return transactionHandler.execute(task);
    }

    /**
     * 先加锁, 后开启事务, 处理失败, 自动回滚事务, 自动释放锁
     */
//    public <T> CommonResult<T> autoExecute(String lockKey, Supplier<CommonResult<T>> task) {
//        Assert.notBlank(lockKey);
//        if (!lockKey.startsWith(RedisKey.REDIS_LOCK_PREFIX)) {
//            lockKey = RedisKey.REDIS_LOCK_PREFIX + lockKey;
//        }
//
//        RLock lock = redissonClient.getLock(lockKey);
//        boolean isLocked = lock.tryLock();
//        if (isLocked) {
//            try {
//                return transactionHandler.autoExecute(task);
//            } finally {
//                lock.unlock();
//            }
//        }
//
//        return CommonResult.failed("请勿重复操作, 请稍后在试");
//    }


    @Transactional(rollbackFor = Throwable.class)
    public void executeWithoutResult(Runnable task) {
        task.run();
    }


}
